package ext.tianma.part.AVLMaterial;

import java.beans.PropertyVetoException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.apache.commons.lang.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.LoggerFactory;

import wt.content.ApplicationData;
import wt.content.ContentHelper;
import wt.content.ContentRoleType;
import wt.content.ContentServerHelper;
import wt.doc.WTDocument;
import wt.fc.PersistenceHelper;
import wt.fc.QueryResult;
import wt.folder.Folder;
import wt.iba.definition.StringDefinition;
import wt.iba.value.StringValue;
import wt.inf.container.ExchangeContainer;
import wt.inf.container.OrgContainer;
import wt.inf.container.WTContainer;
import wt.inf.container.WTContainerHelper;
import wt.inf.container.WTContainerRef;
import wt.lifecycle.LifeCycleHelper;
import wt.lifecycle.LifeCycleTemplate;
import wt.org.WTOrganization;
import wt.org.WTUser;
import wt.part.WTPart;
import wt.part.WTPartMaster;
import wt.query.ArrayExpression;
import wt.query.ClassAttribute;
import wt.query.QueryException;
import wt.query.QuerySpec;
import wt.query.SearchCondition;
import wt.type.ClientTypedUtility;
import wt.type.TypeDefinitionForeignKey;
import wt.type.TypeDefinitionReference;
import wt.type.Typed;
import wt.type.TypedUtility;
import wt.util.WTException;
import wt.util.WTPropertyVetoException;
import wt.vc.config.LatestConfigSpec;

import com.ptc.windchill.enterprise.part.commands.PartDocServiceCommand;

import ext.tianma.bom.service.MaterialsApplicationService;
import ext.tianma.bom.util.DBUtil;
import ext.tianma.bom.util.GenericUtil;
import ext.tianma.model.APLQuantity;
import ext.tianma.part.AVLMaterial.constants.RangeChangeConstants;
import ext.tianma.part.report.searchAPL.service.APLService;
import ext.tianma.part.report.searchAPL.util.APLUtil;
import ext.tianma.upload.CreateDocAndDescribeLink;
import ext.tianma.util.UserUtil;

public class AVLUtil {
	private static final org.slf4j.Logger logger = LoggerFactory.getLogger(AVLUtil.class);
	/**
	 * 获取指定类型的参考文档
	 * @param wtpart
	 * @return
	 * @author xucr
	 * @CreateDate 2020年11月10日
	 */
	public static WTDocument getDoc(WTPart wtpart, String softType) {
		WTDocument doc = null;
		try {
			QueryResult qr = PartDocServiceCommand.getAssociatedReferenceDocuments(wtpart);// 参考文档
			while (qr.hasMoreElements()) {
				doc = (WTDocument) qr.nextElement();
				String typeName = TypedUtility.getTypeIdentifier(doc).getTypename();
				if((typeName.contains(softType))) { //如果是指定类型
					return doc;
				}
			}
		} catch (WTException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 创建文档
	 * @param currentPart
	 * @author xucr
	 * @CreateDate 2020年11月10日
	 */
	public static WTDocument createDoc(String fileName, String filePath, String des) throws Exception {
		/**
		 * 用途：
		 * 1、作为流程主对象
		 * 2、流程审批过程中，APL材料创建者上载报告会关联到此对象中
		 * 3、当流程正常结束后，作为APL材料的文档使用
		 * */
		String number = DBUtil.getNextValue("WTDOCUMENTID_seq", 10);
		WTContainer container = MaterialsApplicationService.getContainerByName(RangeChangeConstants.APLREPORT_WTLIBRARY);
		Folder folder = GenericUtil.getFolder("/Default/进阶报告", container);
		WTDocument doc = GenericUtil.createWTDocument(number, fileName, 
				RangeChangeConstants.APLREPORT, container, folder, des, null, filePath);
		return doc;
	}
	
	/**
	 * 替换主内容
	 * @param doc
	 * @param file
	 * @param des 描述
	 * @throws Exception
	 * @author xucr
	 * @CreateDate 2020年11月11日
	 */
	public static void updateMainContentsFromDoc(WTDocument doc, File file) throws Exception {
		if(null != doc) {
			InputStream io = new FileInputStream(file);
			doc = (WTDocument) GenericUtil.checkout(doc);
			CreateDocAndDescribeLink.replacePrimaryContent(doc, io, file.getName());
			GenericUtil.checkin(doc);
		}
    }
	
	/**
	 * 替换附件
	 * @param doc
	 * @param file
	 * @author xucr
	 * @throws WTException 
	 * @throws IOException 
	 * @throws PropertyVetoException 
	 * @CreateDate 2021年1月13日
	 */
	public static void updateSecondaryFromDoc(WTDocument doc, List<File> files) throws WTException, PropertyVetoException, IOException {
		if(null != doc) {
			doc = (WTDocument) GenericUtil.checkout(doc);
			QueryResult qr = ContentHelper.service.getContentsByRole(doc, ContentRoleType.SECONDARY);
			while (qr.hasMoreElements()) {
				ApplicationData oAppData = (ApplicationData) qr.nextElement();
				ContentServerHelper.service.deleteContent(doc, oAppData);
			}
			for(int i = 0 ; i < files.size(); i++) {
				File file = files.get(i);
				InputStream io = new FileInputStream(file);
				CreateDocAndDescribeLink.updateContent(doc, io, file.getName(), ContentRoleType.SECONDARY);
			}
			GenericUtil.checkin(doc);
		}
	}
	
	/**
	 * APL材料是否在流程中
	 * @param part
	 * @return
	 * @author xucr
	 * @throws JSONException 
	 * @CreateDate 2020年11月11日
	 */
	public static boolean checkProcess(WTPart part, boolean isTrue) throws JSONException {
		boolean isHasSameSubmit = false;
		try {
			QuerySpec qs = new QuerySpec(APLQuantity.class);
			qs.setAdvancedQueryEnabled(true);
			
			JSONObject obj = new JSONObject();
			obj.put("processes", true);
			obj.put("aplPartNumber", part.getNumber());
			List<APLQuantity> quantitys = queryAPLQuantity(obj);
			if(quantitys.size() > 0) {
				isHasSameSubmit = true;
			}
		} catch (QueryException e) {
			e.printStackTrace();
		}
		return isHasSameSubmit; 
	}
	
	
	/**
	 * 查询用量表数据
	 * @param params
	 * @return
	 * @author xucr
	 * @CreateDate 2020年11月6日
	 */
	public static List<APLQuantity> queryAPLQuantity(JSONObject params) {
		List<APLQuantity> quantitys = new ArrayList<APLQuantity>();
		try {
			if(null != params) {
				QuerySpec qs = new QuerySpec(APLQuantity.class);
				int p = qs.appendClassList(WTPartMaster.class, true);
				qs.setAdvancedQueryEnabled(true);
				
				SearchCondition sc = new SearchCondition(APLQuantity.class, 
						"persistable.key.id", WTPartMaster.class, "thePersistInfo.theObjectIdentifier.id");
				qs.appendWhere(sc, new int[] { 0, p });
				
//				SearchCondition sc = new SearchCondition(APLQuantity.class, "thePersistInfo.markForDelete", SearchCondition.EQUAL, 0L);
//				qs.appendWhere(sc, new int[] { 0 });
				
				//料号
				if(params.has("aplPartNumber") && StringUtils.isNotEmpty(params.getString("aplPartNumber"))) {
					String number = params.getString("aplPartNumber");
					SearchCondition sc1 = new SearchCondition(WTPartMaster.class, WTPartMaster.NUMBER, 
							SearchCondition.LIKE, "%" + number + "%");
					qs.appendAnd();
					qs.appendWhere(sc1, new int[] { p });
				}
				
				//使用范围
				if(params.has("usableRange") && StringUtils.isNotEmpty(params.getString("usableRange"))) {
					String usableRange = params.getString("usableRange");
					SearchCondition sc2 = new SearchCondition(APLQuantity.class, APLQuantity.RANGES, SearchCondition.EQUAL, usableRange);
					qs.appendAnd();
					qs.appendWhere(sc2, new int[] { 0 });
				}
				
				//等级
				if(params.has("level") && StringUtils.isNotEmpty(params.getString("level"))) {
					String level = params.getString("level");
					SearchCondition sc3 = new SearchCondition(APLQuantity.class, APLQuantity.LEVELS, SearchCondition.EQUAL, level);
					qs.appendAnd();
					qs.appendWhere(sc3, new int[] { 0 });
				}
				
				//状况
				if(params.has("status") && StringUtils.isNotEmpty(params.getString("status"))) {
					String status = params.getString("status");
					SearchCondition sc4 = new SearchCondition(APLQuantity.class, APLQuantity.STATUS, SearchCondition.EQUAL, status);
					qs.appendAnd();
					qs.appendWhere(sc4, new int[] { 0 });
				}
				
				//责任人：APL材料、创建者、得到料号，再加入到此sql中
				if(params.has("owner") && StringUtils.isNotEmpty(params.getString("owner"))) {
					Map<String, Object> maps = new Hashtable<String, Object>();
					maps.put("creator", params.getString("owner"));
					List<String> nums = queryAPLPart(maps);
					String[] numbers = new String[nums.size()];
					SearchCondition sc5 = new SearchCondition(new ClassAttribute(WTPartMaster.class,
							WTPartMaster.NUMBER), SearchCondition.IN, new ArrayExpression(nums.toArray(numbers)));
					qs.appendAnd();
					qs.appendWhere(sc5, new int[] { p});
				}
				
				//是否流程中
				if(params.has("processes") && null != params.get("processes")) {
					boolean isprocesses = params.getBoolean("processes");
					SearchCondition sc6 = new SearchCondition(APLQuantity.class, APLQuantity.PROCESSES, SearchCondition.IS_TRUE, isprocesses);
					qs.appendAnd();
					qs.appendWhere(sc6, new int[] { 0});
				}
				
				//材料型号
				Hashtable<String, Object> strMap = new Hashtable<String, Object>();//字符串查询
				if(params.has("MaterialType") && StringUtils.isNotBlank(params.getString("MaterialType"))) {
					strMap.put("MaterialType", params.getString("MaterialType"));
				}
				
				//因为材料型号是物料上面的，因此需要构造物料相关的sql
				if(strMap.size() > 0) {
					int pa = qs.appendClassList(WTPart.class, true);
					
					//最新小版本
					SearchCondition s2 = new SearchCondition(WTPart.class,"iterationInfo.latest", SearchCondition.IS_TRUE, true);
					qs.appendAnd();
					qs.appendWhere(s2, new int[] { pa });
					
					//最新大版本
					APLService.addSearchConditionLasterVersion(qs, WTPart.class,null);
					
					//part与master
					SearchCondition s1 = new SearchCondition(WTPart.class,"masterReference.key.id", 
							WTPartMaster.class ,"thePersistInfo.theObjectIdentifier.id");
					qs.appendAnd();
					qs.appendWhere(s1, new int[] { pa, p });
					
					APLUtil.addIBAStringCondition(WTPart.class, qs, strMap, SearchCondition.LIKE, "", true, StringDefinition.class, StringValue.class);
				}
				
				QueryResult qr = PersistenceHelper.manager.find(qs);
				logger.info(">>>:" + qs.toString());
				
				while(qr.hasMoreElements()) {
					Object vo = (Object) qr.nextElement();
					APLQuantity quantity = null;
					if(vo instanceof APLQuantity) {
						quantity = (APLQuantity) vo;
					} else {
						Object as [] = (Object []) vo;
						quantity = (APLQuantity) as[0];
					}
					quantitys.add(quantity);
				}
			}
		} catch (QueryException e) {
			e.printStackTrace();
		} catch (JSONException e) {
			e.printStackTrace();
		} catch (WTException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return quantitys;
	}
	
	/**
	 * 搜索APL材料
	 * @param maps
	 * @return
	 * @throws Exception
	 * @author xucr
	 * @CreateDate 2020年11月9日
	 */
	public static List<String> queryAPLPart(Map<String, Object> maps) throws Exception {
		List<String> partNumbers = new ArrayList<String>();
		
		QuerySpec qs = new QuerySpec(WTPart.class);
	    qs.setAdvancedQueryEnabled(true);
	    
	    //仅查询APL材料
		TypeDefinitionReference clientType = ClientTypedUtility.getTypeDefinitionReference("cn.tianma.AVLMaterial");
		SearchCondition sc = new SearchCondition(WTPart.class,
				Typed.TYPE_DEFINITION_REFERENCE + "." + TypeDefinitionReference.KEY + "." + TypeDefinitionForeignKey.BRANCH_ID, 
				SearchCondition.EQUAL, clientType.getKey().getBranchId());
		qs.appendWhere(sc, new int[] { 0 });
		
		Object creatorObj = maps.get("creator");
		if(null != creatorObj) {
			String creator = (String) creatorObj;
			WTUser user = UserUtil.getUserByName(creator);
			Long userId = user.getPersistInfo().getObjectIdentifier().getId();
			SearchCondition sc1 = new SearchCondition(WTPart.class,"iterationInfo.creator.key.id",SearchCondition.LIKE,userId);
			
			qs.appendAnd();
			qs.appendWhere(sc1, new int[] { 0 });
		}
		logger.info("queryAPLPart sql>>>" + qs.toString());
		QueryResult qr = PersistenceHelper.manager.find(qs);
		qr = new LatestConfigSpec().process(qr);
		
		while(qr.hasMoreElements()) {
			WTPart part = (WTPart) qr.nextElement();
			partNumbers.add(part.getNumber());
		}
		return partNumbers;
	}
	
	/**
	 * 根据Master、使用范围查询APL材料
	 * @param partId
	 * @param range
	 * @return
	 * @author xucr
	 * @CreateDate 2020年11月12日
	 */
	public static APLQuantity getAPLQuantity(Long partId, String range) {
		/**
		 * APL材料：匹配具体APL材料
		 * 范围：匹配具体使用范围
		 * 
		 * APL材料+范围：匹配到某个材料的具体范围，返回值仅一条
		 * */
		APLQuantity quantity = null;
		try {
			QuerySpec qs = new QuerySpec(APLQuantity.class);
			qs.setAdvancedQueryEnabled(true);
			SearchCondition sc1 = new SearchCondition(APLQuantity.class, "persistable.key.id", SearchCondition.EQUAL, partId);
			qs.appendWhere(sc1, new int[] { 0 });
			
			//范围
			SearchCondition sc2 = new SearchCondition(APLQuantity.class, APLQuantity.RANGES, SearchCondition.EQUAL, range);
			qs.appendAnd();
			qs.appendWhere(sc2, new int[] { 0 });
			
			logger.info("getAPLQuantity >> SQL：" + qs.toString());
			QueryResult qr = PersistenceHelper.manager.find(qs);
			while(qr.hasMoreElements()) {
				quantity = (APLQuantity) qr.nextElement();
			}
		} catch (QueryException e) {
			e.printStackTrace();
		} catch (WTException e) {
			e.printStackTrace();
		}
		return quantity;
	}
	
	/**
	 * 根据Master、使用范围查询APL材料
	 * @param partId
	 * @param range
	 * @return
	 * @author xucr
	 * @CreateDate 2020年11月12日
	 */
	public static List<APLQuantity> getAPLQuantitys(Long partId, String [] ranges) {
		/**
		 * APL材料：匹配具体APL材料
		 * 范围：匹配具体使用范围
		 * 
		 * APL材料+范围：匹配到某个材料的具体范围，返回值仅一条
		 * */
		List<APLQuantity> quantitys = new ArrayList<APLQuantity>();
		try {
			QuerySpec qs = new QuerySpec(APLQuantity.class);
			qs.setAdvancedQueryEnabled(true);
			SearchCondition sc1 = new SearchCondition(APLQuantity.class, "persistable.key.id", SearchCondition.EQUAL, partId);
			qs.appendWhere(sc1, new int[] { 0 });
			
			//范围
			SearchCondition sc2 = new SearchCondition(new ClassAttribute(APLQuantity.class,
					APLQuantity.RANGES), SearchCondition.IN, new ArrayExpression(ranges));
			qs.appendAnd();
			qs.appendWhere(sc2, new int[] { 0 });
			
			logger.info("getAPLQuantity >> SQL：" + qs.toString());
			QueryResult qr = PersistenceHelper.manager.find(qs);
			while(qr.hasMoreElements()) {
				APLQuantity quantity = (APLQuantity) qr.nextElement();
				quantitys.add(quantity);
			}
		} catch (QueryException e) {
			e.printStackTrace();
		} catch (WTException e) {
			e.printStackTrace();
		}
		return quantitys;
	}
	
	/**
	 * 反射获取对象的属性值
	 * @param object
	 * @param methodName
	 * @return
	 * @author xucr
	 * @CreateDate 2020年11月13日
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static Object getAttributeObjValForReflex(Object object, String methodName) {
		Object value = "";
		if (object != null) {
			try {
				Class classObj = object.getClass();
				Method method = classObj.getMethod(methodName, new Class[0]);
				value = method.invoke(object, new Object[0]);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return value;
	}
	
	/**
	 * 获取属性值
	 * @param object
	 * @param methodName
	 * @param classObj 返回值类型
	 * @return
	 * @author xucr
	 * @CreateDate 2020年11月13日
	 */
	public static Class getObjForReflex(Object object, String methodName, Class classObj) {
		Class classValue = null;
		if (object != null) {
			try {
				Object objValue = getAttributeObjValForReflex(object, methodName);
				classValue = (Class) objValue;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return classValue;
	}
	
	/**
	 * 获取八大范围在属性中的key、value
	 * @param key
	 * @return
	 * @throws JSONException
	 * @author xucr
	 * @CreateDate 2020年11月9日
	 */
	public static Map<String, String> getIBARangeValue() throws JSONException {
		//八大使用范围属性（IBA属性）的内部名称，均为String类型
		Map<String, String> map = new Hashtable<String, String>();
		try {
			QuerySpec qs = new QuerySpec(StringDefinition.class);
			qs.setAdvancedQueryEnabled(true);
			
			SearchCondition sc = new SearchCondition(new ClassAttribute(StringDefinition.class,
					StringDefinition.NAME), SearchCondition.IN, new ArrayExpression(RangeChangeConstants.USABLERANGES));
			
			qs.appendWhere(sc, new int [] {0});
			logger.info("getRangeValue >>>>" + qs.toString());
			QueryResult qr = PersistenceHelper.manager.find(qs);
			while(qr.hasMoreElements()) {
				StringDefinition sd = (StringDefinition) qr.nextElement();
				map.put(sd.getName(), sd.getDisplayName());
			}
		} catch (QueryException e) {
			e.printStackTrace();
		} catch (WTException e) {
			e.printStackTrace();
		}
		return map;
	}
	
	/**
	 * 获取组织下生命周期模板所有状态
	 * @param templateName
	 * @author xucr
	 * @CreateDate 2020年11月23日
	 */
	public static Vector getStatesByLifeCycleTemplate(String templateName) {
		//AVL材料生命周期
		Vector states = null;
		try {
//			WTOrganization org = SelectUserService.findWTOrganization("tm");
			ExchangeContainer exchangecontainer = WTContainerHelper.service.getExchangeContainer();
	        WTOrganization wtorganization = exchangecontainer.getOrganization();
			OrgContainer orgcontainer = WTContainerHelper.service.getOrgContainer(wtorganization);
			WTContainerRef containerRef = WTContainerRef.newWTContainerRef(orgcontainer);
			LifeCycleTemplate lifeCycle1 = LifeCycleHelper.service.getLifeCycleTemplate(templateName, containerRef);
			states = LifeCycleHelper.service.findStates(lifeCycle1);
		} catch (WTException e) {
			e.printStackTrace();
		}
		return states;
	}
}
